﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BehaviorTrees;

namespace TestProject
{
	/// <summary>
	/// Summary description for ParallelTest
	/// </summary>
	[TestClass]
	public class ParallelTest : BaseTest
	{
		public ParallelTest()
		{
			//
			// TODO: Add constructor logic here
			//
		}

		private TestContext testContextInstance;

		/// <summary>
		///Gets or sets the test context which provides
		///information about and functionality for the current test run.
		///</summary>
		public TestContext TestContext
		{
			get
			{
				return testContextInstance;
			}
			set
			{
				testContextInstance = value;
			}
		}

		#region Additional test attributes
		//
		// You can use the following additional attributes as you write your tests:
		//
		// Use ClassInitialize to run code before running the first test in the class
		// [ClassInitialize()]
		// public static void MyClassInitialize(TestContext testContext) { }
		//
		// Use ClassCleanup to run code after all tests in a class have run
		// [ClassCleanup()]
		// public static void MyClassCleanup() { }
		//
		// Use TestInitialize to run code before running each test 
		// [TestInitialize()]
		// public void MyTestInitialize() { }
		//
		// Use TestCleanup to run code after each test has run
		// [TestCleanup()]
		// public void MyTestCleanup() { }
		//
		#endregion

		/// <summary>
		/// Tests if the actions are really executed in parallel.
		/// </summary>
		[TestMethod]
		public void ParallelActions()
		{
			entity = new TestEntity();
			node = new Parallel<TestEntity>()
			{
				new BehaviorTrees.Action<TestEntity>(TestEntity.IncreaseX),
				new BehaviorTrees.Action<TestEntity>(TestEntity.IncreaseY),
				new BehaviorTrees.Action<TestEntity>(TestEntity.IncreaseZ)
			};
			Task<TestEntity> task = node.Evaluate(entity);
			// ONE execcution call
			task.Execute(entity, null);
			Assert.AreEqual(entity.x, entity.y);
			Assert.AreEqual(entity.y, entity.z);
			Assert.AreEqual(entity.z, 1);
		}
		/// <summary>
		/// Checks if the master node's success in parallel node is the success of the whole parallel.
		/// We assume that task succeeds right after the master node's task succeeds, and second
		/// action in parallel doesn't even get chance to run.
		/// </summary>
		[TestMethod]
		public void ParallelWithMasterSuccess()
		{
			entity = new TestEntity();
			node = new Parallel<TestEntity>(new BehaviorTrees.Action<TestEntity>(TestEntity.Success))
			{
				new BehaviorTrees.Action<TestEntity>(TestEntity.IncreaseX)
			};
			task = node.Evaluate(entity);
			task.Execute(entity, null);

			Assert.AreEqual(0, entity.x);
		}
		/// <summary>
		/// Checks if the master node's failure in parallel node is the failure of the whole parallel.
		/// We assume that task fails right after the master node's task fails, and second
		/// action in parallel doesn't even get chance to run.
		/// </summary>
		[TestMethod]
		public void ParallelWithMasterFailure()
		{
			entity = new TestEntity();
			node = new Parallel<TestEntity>(new BehaviorTrees.Action<TestEntity>(TestEntity.Fail))
			{
				new BehaviorTrees.Action<TestEntity>(TestEntity.IncreaseX)
			};
			task = node.Evaluate(entity);
			task.Execute(entity, null);

			Assert.AreEqual(0, entity.x);
		}
	}
}
